package cn.xiaopengstack.domain.award.service.impl;

import cn.xiaopengstack.domain.activity.model.entity.RaffleActivityEntity;
import cn.xiaopengstack.domain.activity.repository.IRaffleActivityRepository;
import cn.xiaopengstack.domain.award.model.entity.*;
import cn.xiaopengstack.domain.award.service.IAwardService;
import cn.xiaopengstack.domain.award.aggregate.UserAwardOrderAggregate;
import cn.xiaopengstack.domain.award.event.SendAwardMessageEvent;
import cn.xiaopengstack.domain.award.model.valobj.TaskStateVO;
import cn.xiaopengstack.domain.award.repository.IRaffleAwardRepository;
import cn.xiaopengstack.domain.award.service.distribute.IDistributeAward;
import cn.xiaopengstack.domain.strategy.model.entity.StrategyAwardEntity;
import cn.xiaopengstack.domain.strategy.model.valobj.RuleTreeNodeVO;
import cn.xiaopengstack.domain.strategy.model.valobj.RuleTreeVO;
import cn.xiaopengstack.domain.strategy.repository.IStrategyRepository;
import cn.xiaopengstack.domain.task.model.TaskEntity;
import cn.xiaopengstack.types.enums.ResponseCode;
import cn.xiaopengstack.types.exception.AppException;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * @author jiangyangang
 */
@Service
@Slf4j
public class AwardService implements IAwardService {

    private final IRaffleAwardRepository raffleAwardRepository;

    private final IStrategyRepository strategyRepository;

    private final IRaffleActivityRepository raffleActivityRepository;

    private final Map<String , IDistributeAward> distributeAwardMap;

    public AwardService(IRaffleAwardRepository raffleAwardRepository, IStrategyRepository strategyRepository, IRaffleActivityRepository raffleActivityRepository, Map<String, IDistributeAward> distributeAwardMap) {
        this.raffleAwardRepository = raffleAwardRepository;
        this.strategyRepository = strategyRepository;
        this.raffleActivityRepository = raffleActivityRepository;
        this.distributeAwardMap = distributeAwardMap;
    }

    @Override
    public void createUserAwardOrder(UserAwardOrderEntity orderEntity) {

        SendAwardMessageEvent.SendAwardMessage message = new SendAwardMessageEvent.SendAwardMessage();
        message.setAwardId(orderEntity.getAwardEntity().getAwardId());
        message.setUserId(orderEntity.getUser().getUserId());
        message.setOrderId(orderEntity.getOrderId());
        message.setActivityId(orderEntity.getActivityEntity().getActivityId());

        SendAwardMessageEvent<SendAwardMessageEvent.SendAwardMessage> event = new SendAwardMessageEvent<>(message, orderEntity.getOrderId());

        TaskEntity taskEntity = new TaskEntity();
        taskEntity.setUser(orderEntity.getUser());
        taskEntity.setTopic(event.topic());
        taskEntity.setMessage(JSONObject.toJSONString(event.payload()));
        taskEntity.setMessageId(event.payload().getId());
        taskEntity.setState(TaskStateVO.create);

        UserAwardOrderAggregate userAwardOrderAggregate = new UserAwardOrderAggregate();
        userAwardOrderAggregate.setUserAwardOrderEntity(orderEntity);
        userAwardOrderAggregate.setTaskEntity(taskEntity);
        userAwardOrderAggregate.setSendAwardMessageEvent(event);

        raffleAwardRepository.createUserAwardOrder(userAwardOrderAggregate);
    }

    @Override
    public List<StrategyAwardEntity> queryRaffleStrategyAwardList(String userId, Long activityId) {
        RaffleActivityEntity activityEntity = raffleActivityRepository.queryRaffleActivityByActivityId(activityId);
        List<StrategyAwardEntity> strategyAwardEntityList = strategyRepository.queryStrategyAwardInfoList(activityEntity.getStrategyId());

        // 使用parallel并行流处理，建议在jdk9之后使用可以指定线程池
        strategyAwardEntityList.stream().parallel().forEach(awardEntity -> {
            // 配置奖品锁定信息
            RuleTreeVO ruleTreeVO = strategyRepository.queryRuleTreeVOByTreeId(awardEntity.getRuleModels()); // 查询用户当前中奖的次数
            int userWinAwardCount = raffleAwardRepository.queryUserWinLotteryCount(userId, awardEntity.getAwardId());
            Map<String, RuleTreeNodeVO> treeNodeMap = ruleTreeVO.getTreeNodeMap();

            awardEntity.doInitLock(treeNodeMap, userWinAwardCount);
        });

        return strategyAwardEntityList;
    }

    @Override
    public void distributeAward(DistributeAwardEntity distributeAwardEntity) {
        // 查询发奖记录
        Optional<UserAwardRecordEntity> userAwardRecordEntityOpt = raffleAwardRepository.queryAwardRecordByOrderId(distributeAwardEntity.getUserId(), distributeAwardEntity.getOrderId());
        UserAwardRecordEntity userAwardRecordEntity = userAwardRecordEntityOpt.orElseThrow(() -> new AppException(ResponseCode.DISTRIBUTE_AWARD_ERROR.getCode(), ResponseCode.DISTRIBUTE_AWARD_ERROR.getInfo()));

        // 查询奖品信息
        Optional<AwardEntity> awardEntityOpt = raffleAwardRepository.queryAwardEntity(userAwardRecordEntity.getAwardId());
        AwardEntity awardEntity = awardEntityOpt.orElseThrow(() -> new AppException(ResponseCode.DISTRIBUTE_AWARD_NO_AWARD_ERROR.getCode(), ResponseCode.DISTRIBUTE_AWARD_NO_AWARD_ERROR.getInfo()));
        IDistributeAward distributeAward = distributeAwardMap.get(awardEntity.getAwardKey());
        if (Objects.isNull(distributeAward)) {
            throw new AppException(ResponseCode.DISTRIBUTE_AWARD_HANDLER_ERROR.getCode(), ResponseCode.DISTRIBUTE_AWARD_HANDLER_ERROR.getInfo());
        }

        // 分发奖励
        distributeAward.distribute(DistributeMatterEntity.builder()
                        .userAwardRecordEntity(userAwardRecordEntity)
                        .awardEntity(awardEntity)
                        .userId(distributeAwardEntity.getUserId())
                .build());
    }

    public static void main(String[] args) {
        System.out.println(Math.abs((12 % 5) - 5));
    }
}
